<template>
    <el-dialog
      v-model="dialogVisible"
      title="文件预览"
      width="80%"
      :destroy-on-close="true"
      class="file-preview-dialog"
    >
      <!-- 多文件切换 -->
      <el-radio-group 
        v-model="fileSelect" 
        size="large" 
        style="margin-bottom:10px" 
        v-if="fileArr.length > 1" 
        @change="bindChangeRadio"
      >
        <el-radio-button 
          v-for="(item, index) in fileArr" 
          :key="index" 
          :label="index"
        >
          {{ '文件' + (index + 1) }}
        </el-radio-button>
      </el-radio-group>
  
      <!-- 下载按钮 -->
      <div>
        <el-link 
          :href="currentFile" 
          :underline="false" 
          target="_blank" 
          class="margin-bottom"
        >
          <el-button>下载</el-button>
        </el-link>
      </div>
  
      <!-- Word预览 -->
      <div v-if="isWordFile" ref="docxRef" class="word-div"></div>
  
      <!-- Excel预览 -->
      <div v-if="isExcelFile" class="xlsx-div">
        <el-tabs v-model="activeName" type="border-card">
          <el-tab-pane 
            v-for="(item, index) in excelSheet" 
            :key="index" 
            :label="item.name" 
            :name="item.name"
          >
            <div class="table" v-html="item.html"></div>
          </el-tab-pane>
        </el-tabs>
      </div>
  
      <!-- PDF预览 -->
      <div v-if="isPdfFile" class="pdf-div">
        <iframe v-if="iframeUrl" :src="iframeUrl" frameborder="0" style="width: 100%; height: 99%"></iframe>
        <div v-else class="loading-error">
          <i class="el-icon-document"></i>
          <div>PDF 加载失败</div>
          <el-button @click="retryLoadPdf" size="small" type="primary">重试</el-button>
        </div>
      </div>
      
      <!-- 图片预览 -->
      <div v-if="isImageFile" class="image-div">
        <el-image 
          :src="currentFile" 
          :preview-src-list="[currentFile]" 
          fit="contain"
          style="width: 100%; height: 70vh;" 
        >
          <template #error>
            <div class="image-error">
              <i class="el-icon-picture-outline"></i>
              <div>加载图片失败</div>
            </div>
          </template>
        </el-image>
      </div>
    </el-dialog>
  </template>
  
  <script>
  import axios from 'axios'
  import * as XLSX from 'xlsx'
  import { renderAsync } from 'docx-preview'
  
  export default {
    name: 'FilePreview',
    data() {
      return {
        dialogVisible: false,
        fileSelect: 0,
        fileArr: [],
        excelSheet: [],
        activeName: '',
        iframeUrl: '',
        currentFile: '',
        isLoading: false,
        lastPdfUrl: ''
      }
    },
    computed: {
      isWordFile() {
        return ['doc', 'docx'].includes(this.getFileType(this.currentFile))
      },
      isExcelFile() {
        return ['xls', 'xlsx'].includes(this.getFileType(this.currentFile))
      },
      isPdfFile() {
        return this.getFileType(this.currentFile) === 'pdf'
      },
      isImageFile() {
        return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(this.getFileType(this.currentFile))
      }
    },
    methods: {
      // 打开预览
      open(urls) {
        if (!urls) {
          this.$message.error('请提供文件地址')
          return
        }
        // import.meta.env.VITE_APP_BASE
        this.fileArr = urls.split(',').map(url => url.trim())
        this.currentFile = this.fileArr[0]
        this.fileSelect = 0
        this.dialogVisible = true

        
        this.previewFile(this.currentFile)
      },
  
      // 切换文件
      bindChangeRadio(index) {
        this.currentFile = this.fileArr[index]
        this.previewFile(this.currentFile)
      },
  
      // 预览文件
      async previewFile(url) {
        const fileType = this.getFileType(url)
        this.isLoading = true
        
        // 如果是图片，直接使用URL预览，不需要额外处理
        if (this.isImageFile) {
          this.isLoading = false
          return
        }
        
        try {
          // 对于PDF文件，使用改进的viewPdf方法
          if (fileType === 'pdf') {
            this.lastPdfUrl = url
            await this.viewPdf(url)
            this.isLoading = false
            return
          }
          
          const res = await axios({
            url: url,
            method: 'get',
            responseType: 'blob',
            timeout: 30000
          })
  
          if (res.status === 200) {
            if (['doc', 'docx'].includes(fileType)) {
              await this.previewWord(res.data)
            } else if (['xls', 'xlsx'].includes(fileType)) {
              await this.previewExcel(res.data)
            }
          }
        } catch (error) {
          console.error('预览失败:', error)
          this.$message.error('文件预览失败')
        } finally {
          this.isLoading = false
        }
      },
  
      // 重试加载PDF
      retryLoadPdf() {
        if (this.lastPdfUrl) {
          this.viewPdf(this.lastPdfUrl)
        }
      },
  
      // Word预览
      async previewWord(blob) {
        try {
          // 确保DOM已经更新
          this.$nextTick(async () => {
            if (this.$refs.docxRef) {
              await renderAsync(blob, this.$refs.docxRef)
            }
          })
        } catch (error) {
          console.error('Word预览失败:', error)
          this.$message.error('Word文件预览失败')
        }
      },
  
      // Excel预览
      previewExcel(blob) {
        const reader = new FileReader()
        reader.readAsArrayBuffer(blob)
        reader.onload = (e) => {
          try {
            const arrayBuffer = e.target.result
            const workbook = XLSX.read(new Uint8Array(arrayBuffer), { 
              type: 'array',
              cellStyles: true,
              cellHTML: true
            })
            
            const list = []
            const sheetNames = workbook.SheetNames
            
            if (sheetNames.length > 0) {
              this.activeName = sheetNames[0]
              
              for (const sheetName of sheetNames) {
                let html = ''
                try {
                  html = XLSX.utils.sheet_to_html(workbook.Sheets[sheetName], {
                    header: '<table border="1" cellspacing="0" cellpadding="5">',
                    footer: '</table>'
                  })
                } catch (e) {
                  console.warn('Excel工作表转HTML失败:', e)
                  html = '<div>此工作表无法预览</div>'
                }
                list.push({
                  name: sheetName,
                  html: html
                })
              }
              this.excelSheet = list
            } else {
              this.$message.warning('Excel文件没有工作表')
            }
          } catch (error) {
            console.error('Excel预览失败:', error)
            this.$message.error('Excel文件预览失败')
          }
        }
        
        reader.onerror = (error) => {
          console.error('Excel读取失败:', error)
          this.$message.error('Excel文件读取失败')
        }
      },
  
      // 改进的PDF预览方法
      async viewPdf(url) {
        try {
          // 清除之前的URL
          this.iframeUrl = ''
          // 确保使用正确的响应类型并检查内容类型
          const response = await axios({
            url:import.meta.env.VITE_APP_BASE+ url,
            method: 'get',
            responseType: 'blob',
            timeout: 30000,
            validateStatus: status => status === 200
          })
   
          // this.iframeUrl = URL.createObjectURL(response.data)

          // 验证内容是否为PDF
          const contentType = response.headers['content-type']
          if (contentType && (contentType.includes('application/pdf') || contentType.includes('binary/octet-stream'))) {
            // 创建新的URL对象
            const blob = new Blob([response.data], { type: 'application/pdf' })
            this.iframeUrl = URL.createObjectURL(blob)
          } else {
            console.error('非PDF内容类型:', contentType)
            this.$message.error('不是有效的PDF文件')
          }

        } catch (error) {
          console.error('PDF预览失败:', error)
          this.$message.error('PDF文件加载失败')
          this.iframeUrl = ''
        }
      },
  
      // 获取文件类型
      getFileType(url) {
        try {
          const arr = url.split('.')
          return arr[arr.length - 1].toLowerCase()
        } catch (e) {
          return ''
        }
      }
    }
  }
  </script>
  
  <style lang="scss" scoped>
  .file-preview-dialog {
    :deep(.el-dialog__body) {
      padding: 20px;
    }
  }
  
  .word-div {
    height: 70vh;
  }
  
  .xlsx-div {
    height: 70vh;
  
    :deep(.el-tabs__content) {
      overflow-x: auto;
    }
  
    .table {
      :deep(table) {
        border-collapse: collapse;
        width: 100%;
        
        td, th {
          border: 1px solid #ebeef5;
          padding: 8px;
          min-width: 120px;
        }
      }
    }
  }
  
  .pdf-div {
    height: 70vh;
  }
  
  .image-div {
    height: 70vh;
    display: flex;
    align-items: center;
    justify-content: center;
    
    .image-error {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      color: #909399;
      
      i {
        font-size: 48px;
        margin-bottom: 16px;
      }
    }
  }
  
  .margin-bottom {
    margin-bottom: 10px;
    display: block;
  }
  
  .loading-error {
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: #909399;
    
    i {
      font-size: 48px;
      margin-bottom: 16px;
    }
    
    div {
      margin-bottom: 16px;
    }
  }
  </style>